package com.loongtech.bi.manager.system;

import com.loongtech.bi.entity.system.*;
import com.loongtech.bi.manager.flow.HadoopQueryManager;
import com.loongtech.bi.manager.realTime.DauByDayManager;
import com.loongtech.bi.support.AsyncHttpClientUtils;
import com.loongtech.bi.support.SpringContextUtil;
import com.loongtech.core.util.Time;
import org.apache.commons.lang3.StringUtils;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;

@DisallowConcurrentExecution
public class JobFactory implements Job {
    private static final String NOMORE = "NOMORE";

    /* 日志对象 */
    private BiMonitorResultManager biMonitorResultManager = SpringContextUtil.getBean(BiMonitorResultManager.class);
    private VipFightCoefficientManager vipFightCoefficientManager = SpringContextUtil.getBean(VipFightCoefficientManager.class);
    private BiMonitorGroupConfigManager biMonitorGroupConfigManager = SpringContextUtil.getBean(BiMonitorGroupConfigManager.class);
    private BiMonitorUserConfigManager biMonitorUserConfigManager = SpringContextUtil.getBean(BiMonitorUserConfigManager.class);
    private DauByDayManager dauByDayManager = SpringContextUtil.getBean(DauByDayManager.class);
    private ConfigManager configManager = SpringContextUtil.getBean(ConfigManager.class);

    public void execute(JobExecutionContext context) throws JobExecutionException {
        EntityMonitorConfig job = (EntityMonitorConfig) context.getMergedJobDataMap().get(context.getMergedJobDataMap().getKeys()[0]);
        if (null == job) {
            System.out.println("[产出监控] ********************** job id 为null,返回不执行");
            return;
        }
        System.out.println(job.getInquerySQL());

        HadoopQueryManager queryManager = SpringContextUtil.getBean(HadoopQueryManager.class);
        long startTime = System.currentTimeMillis();
        System.out.println("[产出监控] **********************监控Id为：" + job.getId() + "（" + job.getDescription() + "）的任务开始扫描 " + Time.getNowDateDetailStr() + "************************");

        Map<String, List<EntityMonitorResult>> alarms = new LinkedHashMap<>();
        if (job.getDescription().contains("战斗力")) {
            List<EntityVipFightCoefficient> viplist = vipFightCoefficientManager.findAll();
            if (null != viplist && viplist.size() > 0) {
                for (EntityVipFightCoefficient entity : viplist) {
                    String sql = job.getInquerySQL().replaceAll("@vipk", entity.getVipLevel() + "").replaceAll("@vipv", entity.getVipCoefficient() + "");
                    Map.Entry<List<String>, List<Object[]>> ret = queryManager.executeSQL(sql);
                    if (null != ret && null != ret.getValue() && !ret.getValue().isEmpty()) {
                        updateAlarms(alarms, ret, job, "vip" + entity.getVipLevel());
                    }
                }
            }
        } else {
            Map.Entry<List<String>, List<Object[]>> ret = queryManager.executeSQL(job.getInquerySQL());
            if (null != ret && null != ret.getValue() && !ret.getValue().isEmpty()) {
                updateAlarms(alarms, ret, job, "");
            }
        }

        // send alarm
        if (alarms.size() > 0 && diamondCondition(job.getId(), alarms)) {
            boolean allNull = true;
            for (Map.Entry<String, List<EntityMonitorResult>> entry : alarms.entrySet()) {
                if (entry.getValue() != null && entry.getValue().size() > 0) {
                    allNull = false;
                    break;
                }
            }
            if (allNull) {
                return;
            }

            System.out.println("[产出监控] ********************** 扫描到新的告警！！！**********************");

            EntityMonitorGroupConfig groupEntity = biMonitorGroupConfigManager.getByQuery("from EntityMonitorGroupConfig where id = ?", job.getGroupId());
            List<Integer> userIdList = biMonitorUserConfigManager.findByQuery("select userId from EntityMonitorUserGroup where groupId = ?", job.getGroupId());
            if (null != groupEntity && null != groupEntity.getNotifyType() && groupEntity.getNotifyType().length() != 0 && null != userIdList && !userIdList.isEmpty()) {
                // make context
                StringBuffer emailContext = getEmailContext(job, alarms);
                StringBuffer messageContext = getMessageContext(job, alarms);
                StringBuffer weChatContext = getWeChatContext(job, alarms);

                String[] strArray = groupEntity.getNotifyType().split("-");
                for (Integer userId : userIdList) {
                    EntityMonitorUserConfig entity = biMonitorUserConfigManager.getByQuery("from EntityMonitorUserConfig where id = ?", userId);
                    if (emailContext != null && emailContext.length() > 0 && containCheck("邮箱", strArray)) {
                        System.out.println("[产出监控] **********************给" + entity.getEmail() + "发邮件 *********************");
                        sendMail(entity.getEmail(), emailContext);
                    }
                    if (messageContext != null && messageContext.length() > 0 && containCheck("手机号", strArray)) {
                        System.out.println("[产出监控] **********************给" + entity.getPhoneNum() + "发短信 *********************");
                        sendMessage(entity.getPhoneNum(), messageContext);
                    }
                    if (containCheck("语音号", strArray) && null != groupEntity.getVoiceTemplate() && groupEntity.getVoiceTemplate().length() > 0) {
                        System.out.println("[产出监控] **********************给" + entity.getVoiceNum() + "发语音通知 *********************");
                        voiceCall(entity.getVoiceNum(), groupEntity.getVoiceTemplate());
                    }
                    if (weChatContext != null && weChatContext.length() > 0 && containCheck("微信", strArray)) {
                        System.out.println("[产出监控] **********************给" + entity.getWeChat() + "发微信 *********************");
                        sendWeChat(entity.getWeChat(), weChatContext);
                    }
                }
            }
        }
        long timeComsume = (System.currentTimeMillis() - startTime) / 1000;
        System.out.println("[产出监控] ********************** 监控Id为：" + job.getId() + "（" + job.getDescription() + "）的任务扫描结束 " + Time.getNowDateDetailStr() + "用时" + timeComsume + "秒 ************************");
    }

    /**
     * Author: yuri
     * Description: 存放异常结果到map中
     * Date: 17:13 2016/11/18
     */
    private void updateAlarms(Map<String, List<EntityMonitorResult>> alarms, Map.Entry<List<String>, List<Object[]>> ret, EntityMonitorConfig job, String moreMsg) {
        moreMsg = StringUtils.isEmpty(moreMsg) ? NOMORE : moreMsg;
        List<EntityMonitorResult> list = alarms.get(moreMsg);
        if (list == null) {
            list = new ArrayList<>();
            alarms.put(moreMsg, list);
        }

        for (int i = 0; i < ret.getValue().size(); i++) {
            int jobId = job.getId();
            String serverId = ret.getValue().get(i)[0].toString();
            String userOrGroupName = ret.getValue().get(i)[1].toString();
            String result = ret.getValue().get(i)[2].toString();

            EntityMonitorResult res = biMonitorResultManager.getByQuery("from EntityMonitorResult where jobId = ? and userOrGroupName = ? and serverId = ? and creatTime >= ?", jobId, userOrGroupName, serverId, Time.getBeginningOfDay(System.currentTimeMillis()));
            if (res == null) { // 存
                EntityMonitorResult entityMonitorReult = new EntityMonitorResult();
                entityMonitorReult.setUserOrGroupName(userOrGroupName);
                entityMonitorReult.setResult(result);
                entityMonitorReult.setServerId(serverId);
                entityMonitorReult.setJobId(jobId);
                entityMonitorReult.setMoreMsg(moreMsg);
                biMonitorResultManager.persist(entityMonitorReult);

                list.add(entityMonitorReult);
            } else {
                if (!res.getResult().equals(result)) { // 改
                    res.setResult(result);
                    biMonitorResultManager.merge(res);
                    list.add(res);
                }
            }

        }
    }


    private boolean containCheck(String str, String[] list) {
        if (null == list || list.length == 0) {
            return false;
        }
        for (String strInList : list) {
            if (strInList.equals(str)) {
                return true;
            }
        }
        return false;
    }

    private StringBuffer getEmailContext(EntityMonitorConfig job, Map<String, List<EntityMonitorResult>> alarms) {
        StringBuffer result = new StringBuffer();
        result.append("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>" +
                "<html xmlns='http://www.w3.org/1999/xhtml'>" +
                "<head>" +
                "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />" +
                "<meta name='viewport' content='width=device-width, initial-scale=1.0'/>" +
                "</head>");
        result.append("<body><div align='center'>");
        result.append("[").append(configManager.getConfigValueByName(ConfigManager.PROJECT_NAME)).append("]");
        for (Map.Entry<String, List<EntityMonitorResult>> entry : alarms.entrySet()) {
            String moreMsg = entry.getKey();
            List<EntityMonitorResult> als = entry.getValue();
            if (als != null && als.size() > 0) {
                String[] res = calculateAlarm(als);
                result.append("任务").append(job.getId()).append("-").append(job.getDescription());
                if (!NOMORE.equals(moreMsg)) {
                    result.append("[");
                    result.append(moreMsg);
                    result.append("]");
                }
                result.append(" 产生新异常，异常条数为：").append(als.size()).append("。异常最大值为：").append(res[0]).append("，最小值为：").append(res[1]).append("，平均值为：").append(res[2]).append(". 请及时关注！");
                result.append("<br/>");

            }
        }
        result.append("</div>");
        result.append("</body></html>");
        return result;
    }

    private StringBuffer getMessageContext(EntityMonitorConfig job, Map<String, List<EntityMonitorResult>> alarms) {
        StringBuffer result = new StringBuffer();
        result.append("[").append(configManager.getConfigValueByName(ConfigManager.PROJECT_NAME)).append("]");
        for (Map.Entry<String, List<EntityMonitorResult>> entry : alarms.entrySet()) {
            String moreMsg = entry.getKey();
            List<EntityMonitorResult> als = entry.getValue();
            if (als != null && als.size() > 0) {
                String[] res = calculateAlarm(als);
                result.append("任务").append(job.getId()).append("-").append(job.getDescription());
                if (!NOMORE.equals(moreMsg)) {
                    result.append("[");
                    result.append(moreMsg);
                    result.append("]");
                }
                result.append(" 产生新异常，异常条数为：").append(als.size()).append("。异常最大值为：").append(res[0]).append("，最小值为：").append(res[1]).append("，平均值为：").append(res[2]).append(". 请及时关注！");
                result.append(System.getProperty("line.separator"));
            }
        }
        return result;
    }


    private StringBuffer getWeChatContext(EntityMonitorConfig job, Map<String, List<EntityMonitorResult>> alarms) {
        StringBuffer result = new StringBuffer();
        result.append("[").append(configManager.getConfigValueByName(ConfigManager.PROJECT_NAME)).append("]");
        for (Map.Entry<String, List<EntityMonitorResult>> entry : alarms.entrySet()) {
            String moreMsg = entry.getKey();
            List<EntityMonitorResult> als = entry.getValue();
            if (als != null && als.size() > 0) {
                String[] res = calculateAlarm(als);

                result.append("任务").append(job.getId()).append("-").append(job.getDescription());
                if (!NOMORE.equals(moreMsg)) {
                    result.append("[");
                    result.append(moreMsg);
                    result.append("]");
                }
                result.append(" 产生新异常，异常条数为：").append(als.size()).append("。异常最大值为：").append(res[0]).append("，最小值为：").append(res[1]).append("，平均值为：").append(res[2]).append(". 请及时关注！");
//                result.append(System.getProperty("line.separator"));
                result.append("   ");
            }
        }
        return result;
    }

    private void sendMail(String email, StringBuffer context) {
        Map<String, Object> params = new HashMap<>();
       String url = configManager.getConfigValueByName(ConfigManager.ALARM_HOST) + "/mail";
//       String url = "https://yy-ql.zulong.com/smskits/mail";
        params.put("subject", "异常告警！");
        params.put("receivers", email);
        params.put("content", context.toString());
        params.put("gameId", "209");
        params.put("ccs", "zulongops@zulong.com");
        try {
            AsyncHttpClientUtils.asyncSendHttpPostRequest(url, params);
        } catch (IOException | InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
/*
   public static void main(String[] args) {
       StringBuffer result = new StringBuffer();
       result.append("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>" +
               "<html xmlns='http://www.w3.org/1999/xhtml'>" +
               "<head>" +
               "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />" +
               "<meta name='viewport' content='width=device-width, initial-scale=1.0'/>" +
               "</head>");
       result.append("<body><div align='center'>");

               result.append(" 产生新异常，异常条数为：").append(1).append("。异常最大值为：").append(222).append("，最小值为：").append(111).append("，平均值为：").append(3333).append(". 请及时关注！");
               result.append(System.getProperty("line.separator"));
       result.append("</div>");
       result.append("</body></html>");



         //  sendMail("liuchengyu@zulong.com", result);
    }*/

    private void sendMessage(String phoneNum, StringBuffer context) {
        Map<String, Object> params = new HashMap<>();
        String url = configManager.getConfigValueByName(ConfigManager.ALARM_HOST) + "/sendsms";
        params.put("phone", phoneNum);
        params.put("message", context.toString());
        try {
            AsyncHttpClientUtils.asyncSendHttpGetRequest(url, params);
        } catch (IOException | InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    private static void sendWeChat(String weChat, StringBuffer context) {
        Map<String, Object> params = new HashMap<>();
//        String url = configManager.getConfigValueByName(ConfigManager.ALARM_HOST) + "/wechat/wechatPerson";
        String url = "https://yy-ql.zulong.com/smskits/wechat/wechatPerson";
        params.put("client", weChat);
        params.put("content", context.toString());
        try {
            AsyncHttpClientUtils.asyncSendHttpGetRequest(url, params);
        } catch (IOException | ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        StringBuffer ss = new StringBuffer();
        ss.append("hello world 你好    ");
        sendWeChat("18514533356",ss);



    }

    private void voiceCall(String voiceNum, String voiceTemplate) {
        Map<String, Object> params = new HashMap<>();
        String url = configManager.getConfigValueByName(ConfigManager.ALARM_HOST) + "/voice";
        params.put("destNumber", voiceNum);
        params.put("voiceCode", voiceTemplate);
        try {
            AsyncHttpClientUtils.asyncSendHttpGetRequest(url, params);
        } catch (IOException | InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }


    private String[] calculateAlarm(List<EntityMonitorResult> alarms) {
        String[] res = new String[3];
        if (null != alarms && alarms.size() != 0) {
            int length = alarms.size();
            Long max = Long.MIN_VALUE;
            Long min = Long.MAX_VALUE;
            Double sum = 0.0;

            for (EntityMonitorResult alarm : alarms) {
                long value = (long) Double.parseDouble(alarm.getResult());
                if (value > max) {
                    max = value;
                }
                if (value < min) {
                    min = value;
                }
                sum = sum + value;
            }
            res[0] = max.toString();
            res[1] = min.toString();
            Double avg = sum / length;
            DecimalFormat df = new DecimalFormat("#.00");
            res[2] = df.format(avg);
        }
        return res;
    }

    private Boolean diamondCondition(Integer jobId, Map<String, List<EntityMonitorResult>> alarms) {
        double dauPerDay = Double.parseDouble(dauByDayManager.getAllActiveUserByConditions(new Date(), "0", "0", "0"));
        return jobId != 39 || (alarms.get(NOMORE).size() / dauPerDay > 0.05);
    }
}
